package com.xc.file.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xc.core.bean.PagingBean;
import com.xc.core.bean.QueryBean;
import com.xc.core.dto.PagingDto;
import com.xc.core.enums.RedisPrefix;
import com.xc.core.enums.RedisTime;
import com.xc.core.utils.RedisUtils;
import com.xc.core.utils.ServiceUtils;
import com.xc.file.bean.ShareBean;
import com.xc.file.config.Constants;
import com.xc.file.dto.FileDto;
import com.xc.file.dto.FolderDto;
import com.xc.file.dto.FolderFileDto;
import com.xc.file.dto.ShareDto;
import com.xc.file.entity.FileEntity;
import com.xc.file.entity.FolderEntity;
import com.xc.file.entity.ShareEntity;
import com.xc.file.entity.ShareFolderFileEntity;
import com.xc.file.enums.FailCode;
import com.xc.file.mapper.FileMapper;
import com.xc.file.mapper.FolderMapper;
import com.xc.file.mapper.ShareFolderFileMapper;
import com.xc.file.mapper.ShareMapper;
import com.xc.file.model.ShareIdModel;
import com.xc.file.service.FileService;
import com.xc.file.service.FolderService;
import com.xc.file.service.ShareService;
import com.xc.tool.utils.ObjectUtils;
import com.xc.tool.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>共享文件实现</p>
 *
 * @author xc
 * @version v1.0
 */
@Service
@Slf4j
public class ShareServiceImpl extends ServiceImpl<ShareMapper, ShareEntity> implements ShareService {

    @Autowired
    private ShareFolderFileMapper shareFolderFileMapper;
    @Autowired
    private FolderService folderService;
    @Autowired
    private FolderMapper folderMapper;
    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private ShareMapper shareMapper;
    @Autowired
    private FileService fileService;
    @Autowired
    private Constants constants;

    @Override
    @Transactional
    public ShareDto createUserShare(String userId, ShareBean shareBean) {
        //创建共享文件
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setValidTime(shareBean.getValidTime());
        if (shareBean.getNeedCode() == 0) {
            String drawCode = StringUtils.random(6);
            shareEntity.setDrawCode(drawCode);
        }
        shareEntity.setRemark(shareBean.getRemark());
        shareEntity.setUserId(userId);
        shareEntity.setCode(StringUtils.generateOnlyId(constants.getMachineId()));
        if (!this.save(shareEntity)) {
            throw FailCode.CREATE_SHARE_FILE_FAIL.getOperateException();
        }
        String fileName = "";
        //文件共享
        for (int i = 0; i < shareBean.getFileIds().size(); i++) {
            String id = shareBean.getFileIds().get(i);
            FileEntity fileEntity = fileMapper.selectById(id);
            if (i == 0) {
                fileName = fileEntity.getName();
            }
            if (!fileEntity.getUserId().equals(userId)) {
                throw FailCode.NOT_OPERATE_AUTHORITY.getOperateException();
            }
            ShareFolderFileEntity share = new ShareFolderFileEntity();
            share.setShareId(shareEntity.getId());
            share.setFileId(fileEntity.getId());
            share.setIsRoot(0);
            if (!retBool(shareFolderFileMapper.insert(share))) {
                throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
        }
        //文件夹共享
        String folderName = "";
        for (int i = 0; i < shareBean.getFolderIds().size(); i++) {
            String id = shareBean.getFolderIds().get(i);
            FolderEntity folderEntity = folderMapper.selectById(id);
            if (i == 0) {
                folderName = folderEntity.getName();
            }
            if (!folderEntity.getUserId().equals(userId)) {
                throw FailCode.NOT_OPERATE_AUTHORITY.getOperateException();
            }
            ShareFolderFileEntity shareFolderFileEntity = new ShareFolderFileEntity();
            shareFolderFileEntity.setFolderId(folderEntity.getId());
            shareFolderFileEntity.setShareId(shareEntity.getId());
            shareFolderFileEntity.setIsRoot(0);
            if (!retBool(shareFolderFileMapper.insert(shareFolderFileEntity))) {
                throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
            //创建下级共享文件关联
            folderService.subdirectoryHandle(id, null, (subdirectoryInfo) -> {
                if (subdirectoryInfo.getIsFile()) {
                    List<FileEntity> files = subdirectoryInfo.getFiles();
                    for (FileEntity file : files) {
                        ShareFolderFileEntity share = new ShareFolderFileEntity();
                        share.setFileId(file.getId());
                        share.setIsRoot(1);
                        share.setShareId(shareEntity.getId());
                        if (!retBool(shareFolderFileMapper.insert(share))) {
                            throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
                        }
                    }
                } else {
                    FolderEntity folder = subdirectoryInfo.getFolder();
                    ShareFolderFileEntity shareFolder = new ShareFolderFileEntity();
                    shareFolder.setFolderId(folder.getId());
                    shareFolder.setShareId(shareEntity.getId());
                    shareFolder.setIsRoot(1);
                    if (!retBool(shareFolderFileMapper.insert(shareFolder))) {
                        throw FailCode.CREATE_FILE_SHARE_FILE_FAIL.getOperateException();
                    }
                }
            });
        }
        // 更新共享名称
        String name;
        if (shareBean.getFileIds().size() == 1) {
            name = fileName;
        } else if (shareBean.getFolderIds().size() == 1) {
            name = folderName;
        } else {
            if (fileName.equals("") && !folderName.equals("")) {
                name = folderName + ",等";
            } else if (!fileName.equals("") && folderName.equals("")) {
                name = fileName + ",等";
            } else {
                name = folderName + "," + fileName + ",等";
            }
        }
        shareEntity.setName(name);
        if (!this.updateById(shareEntity)) {
            throw FailCode.CREATE_SHARE_FILE_FAIL.getOperateException();
        }
        return ObjectUtils.convert(new ShareDto(), shareEntity);
    }

    @Override
    public PagingDto<ShareDto> getUserSharePage(String userId, Integer current, PagingBean pagingBean, ShareBean shareBean) {
        ShareEntity shareEntity = ObjectUtils.convert(new ShareEntity(), shareBean);
        shareEntity.setUserId(userId);
        QueryWrapper<ShareEntity> queryWrapper = ServiceUtils.queryData(pagingBean, shareEntity);
        IPage<ShareEntity> iPage = this.page(new Page<>(current, pagingBean.getSize()), queryWrapper);
        return new PagingDto<>(iPage.getTotal(), ObjectUtils.convertList(iPage.getRecords(), ShareDto.class));
    }

    @Override
    public FolderFileDto getShareFolderFile(String shareId, String folderId, String name, QueryBean queryBean) {
        FolderFileDto folderFileDto = new FolderFileDto();
        List<ShareFolderFileEntity> shareFiles = getShareFolderFile(shareId);
        //查询遍历
        List<String> folderIds = new ArrayList<>();
        List<String> fileIds = new ArrayList<>();
        List<String> rootFolderIds = new ArrayList<>();
        List<String> rootFileIds = new ArrayList<>();
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            if (shareFolderFileEntity.getFileId() != null) {
                String id = shareFolderFileEntity.getFileId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    rootFileIds.add(id);
                } else {
                    fileIds.add(id);
                }
            } else {
                String id = shareFolderFileEntity.getFolderId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    rootFolderIds.add(id);
                } else {
                    folderIds.add(id);
                }
            }
        }
        if (constants.getRootFolder().equals(folderId)) {
            //查文件夹
            if (rootFolderIds.size() > 0) {
                QueryWrapper<FolderEntity> queryWrapper = new QueryWrapper<>(new FolderEntity());
                queryWrapper.in("id", rootFolderIds);
                List<FolderEntity> folders = folderMapper.selectList(queryWrapper);
                folderFileDto.setFolders(ObjectUtils.convertList(folders, FolderDto.class));
            } else {
                folderFileDto.setFolders(new ArrayList<>());
            }
            //查文件
            if (rootFileIds.size() > 0) {
                QueryWrapper<FileEntity> query = new QueryWrapper<>(new FileEntity());
                query.in("id", rootFileIds);
                List<FileEntity> files = fileMapper.selectList(query);
                folderFileDto.setFiles(ObjectUtils.convertList(files, FileDto.class));
            } else {
                folderFileDto.setFiles(new ArrayList<>());
            }
        } else if (folderId != null) {
            //查文件夹
            if (folderIds.size() > 0) {
                FolderEntity folderEntity = new FolderEntity();
                folderEntity.setParentId(folderId);
                QueryWrapper<FolderEntity> queryWrapper = new QueryWrapper<>(folderEntity);
                queryWrapper.in("id", folderIds);
                List<FolderEntity> folders = folderMapper.selectList(queryWrapper);
                folderFileDto.setFolders(ObjectUtils.convertList(folders, FolderDto.class));
            } else {
                folderFileDto.setFolders(new ArrayList<>());
            }
            //查文件
            if (fileIds.size() > 0) {
                FileEntity fileEntity = new FileEntity();
                fileEntity.setFolderId(folderId);
                QueryWrapper<FileEntity> query = new QueryWrapper<>(fileEntity);
                query.in("id", fileIds);
                List<FileEntity> files = fileMapper.selectList(query);
                folderFileDto.setFiles(ObjectUtils.convertList(files, FileDto.class));
            } else {
                folderFileDto.setFiles(new ArrayList<>());
            }
        } else if (name != null) {
            //查文件夹
            folderIds.addAll(rootFolderIds);
            if (folderIds.size() > 0) {
                FolderEntity folderEntity = new FolderEntity();
                folderEntity.setName(name);
                QueryWrapper<FolderEntity> queryWrapper = new QueryWrapper<>(folderEntity);
                queryWrapper.in("id", folderIds);
                List<FolderEntity> folders = folderMapper.selectList(queryWrapper);
                folderFileDto.setFolders(ObjectUtils.convertList(folders, FolderDto.class));
            } else {
                folderFileDto.setFolders(new ArrayList<>());
            }
            //查文件
            fileIds.addAll(rootFileIds);
            if (fileIds.size() > 0) {
                FileEntity fileEntity = new FileEntity();
                fileEntity.setName(name);
                QueryWrapper<FileEntity> query = new QueryWrapper<>(fileEntity);
                query.in("id", fileIds);
                List<FileEntity> files = fileMapper.selectList(query);
                folderFileDto.setFiles(ObjectUtils.convertList(files, FileDto.class));
            } else {
                folderFileDto.setFiles(new ArrayList<>());
            }
        } else {
            folderFileDto.setFiles(new ArrayList<>());
            folderFileDto.setFolders(new ArrayList<>());
        }
        String downloadCode = StringUtils.generateOnlyId(constants.getMachineId());
        RedisUtils.set(RedisPrefix.SHARE_DOWNLOAD.getKey() + downloadCode, folderFileDto.getFiles(), RedisTime.SHARE_FILE.getTime());
        fileService.setDownloadUrl(folderFileDto.getFiles(), "/share/" + downloadCode + "/file/");
        return folderFileDto;
    }

    @Override
    @Transactional
    public void deleteUserShare(String userId, String shareId) {
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setUserId(userId);
        shareEntity.setId(shareId);
        shareEntity = shareMapper.selectOne(new QueryWrapper<>(shareEntity));
        if (shareEntity == null) {
            throw FailCode.SHARE_INFO_NOT_EXIST.getOperateException();
        }
        QueryWrapper<ShareFolderFileEntity> queryWrapper = new QueryWrapper<>(new ShareFolderFileEntity(shareId));
        if (shareFolderFileMapper.selectList(queryWrapper).size() != 0) {
            if (!retBool(shareFolderFileMapper.delete(queryWrapper))) {
                throw FailCode.DELETE_FILE_SHARE_FILE_FAIL.getOperateException();
            }
        }
        if (!this.removeById(shareId)) {
            throw FailCode.DELETE_FILE_SHARE_FILE_FAIL.getOperateException();
        }
    }

    @Override
    public ShareDto getShareByCode(String code, String drawCode) {
        ShareEntity shareEntity = new ShareEntity();
        shareEntity.setCode(code);
        shareEntity = shareMapper.selectOne(new QueryWrapper<>(shareEntity));
        if (shareEntity == null) {
            throw FailCode.SHARE_INFO_NOT_EXIST.getOperateException();
        }
        if (shareEntity.getDrawCode() != null && !shareEntity.getDrawCode().equals("")) {
            if (drawCode != null && !drawCode.equals("")) {
                if (shareEntity.getDrawCode() != null) {
                    if (!shareEntity.getDrawCode().equals(drawCode)) {
                        throw FailCode.DRAW_CODE_ERROR.getOperateException();
                    }
                }
            } else {
                return null;
            }
        }
        if (shareEntity.getValidTime() != 0) {
            if ((shareEntity.getCreateTime().getTime() + shareEntity.getValidTime()) < System.currentTimeMillis()) {
                throw FailCode.SHARE_FILE_INVALID.getOperateException();
            }
        }
        shareEntity.setBrowseNum(shareEntity.getBrowseNum() + 1);
        if (!this.updateById(shareEntity)) {
            throw FailCode.UPDATE_SHARE_FILE_FAIL.getOperateException();
        }
        return ObjectUtils.convert(new ShareDto(), shareEntity);
    }


    @Override
    public Long getShareFolderSize(String shareId, String folderId) {
        // 获取下级文件夹及文件
        List<ShareFolderFileEntity> shareFiles = getShareFolderFile(shareId);
        // 查询共享的文件遍历
        List<String> shareFileIds = new ArrayList<>();
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            if (shareFolderFileEntity.getFileId() != null) {
                shareFileIds.add(shareFolderFileEntity.getFileId());
            }
        }
        // 计算大小
        List<String> folderIds = new ArrayList<>();
        folderIds.add(folderId);
        return folderService.getFoldersSize(null, folderIds, shareFileIds);
    }

    @Override
    public List<FolderEntity> getUserParentFolder(String shareId, String folderId) {
        ShareEntity shareEntity = verifyShare(shareId);
        QueryWrapper<ShareFolderFileEntity> queryWrapper = new QueryWrapper<>(new ShareFolderFileEntity(shareEntity.getId()));
        queryWrapper.isNull("file_id");
        //根据共享id查询共享关联
        List<ShareFolderFileEntity> shareFiles = shareFolderFileMapper.selectList(queryWrapper);
        List<String> folderIds = new ArrayList<>();
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            folderIds.add(shareFolderFileEntity.getFolderId());
        }
        List<FolderEntity> folders = new ArrayList<>();
        while (true) {
            FolderEntity folder = new FolderEntity();
            folder.setId(folderId);
            QueryWrapper<FolderEntity> queryWrapper1 = new QueryWrapper<>(folder);
            if (folderIds.size() > 0) {
                queryWrapper1.in("id", folderIds);
                FolderEntity folderEntity = folderMapper.selectOne(queryWrapper1);
                if (folderEntity != null) {
                    folders.add(folderEntity);
                    folderId = folderEntity.getParentId();
                } else {
                    break;
                }
            } else {
                break;
            }
        }
        return folders;
    }

    @Override
    public ShareEntity verifyShare(String shareId) {
        ShareEntity shareEntity = shareMapper.selectById(shareId);
        if (shareEntity == null) {
            throw FailCode.SHARE_FILE_NOT_EXIST.getOperateException();
        }
        if (shareEntity.getValidTime() != 0) {
            if ((shareEntity.getCreateTime().getTime() + shareEntity.getValidTime()) < System.currentTimeMillis()) {
                throw FailCode.SHARE_FILE_INVALID.getOperateException();
            }
        }
        return shareEntity;
    }

    @Override
    public List<ShareFolderFileEntity> getShareFolderFile(String shareId) {
        ShareEntity shareEntity = verifyShare(shareId);
        //根据共享id查询共享关联
        List<ShareFolderFileEntity> shareFiles = shareFolderFileMapper.selectList(new QueryWrapper<>(new ShareFolderFileEntity(shareEntity.getId())));
        if (shareFiles.size() == 0) {
            throw FailCode.SHARE_FILE_NOT_EXIST.getOperateException();
        }
        return shareFiles;
    }

    @Override
    public ShareIdModel getShareIdModelByShareId(String shareId) {
        ShareEntity shareEntity = verifyShare(shareId);
        //查询共享文件信息，修改保存次数
        shareEntity.setPreserveNum(shareEntity.getPreserveNum() + 1);
        if (!this.retBool(shareMapper.updateById(shareEntity))) {
            throw FailCode.UPDATE_SHARE_FILE_FAIL.getOperateException();
        }
        //查询遍历
        List<ShareFolderFileEntity> shareFiles = getShareFolderFile(shareId);
        ShareIdModel shareIdModel = new ShareIdModel();
        shareIdModel.setFileIds(new ArrayList<>());
        shareIdModel.setFolderIds(new ArrayList<>());
        shareIdModel.setRootFileIds(new ArrayList<>());
        shareIdModel.setRootFolderIds(new ArrayList<>());
        for (ShareFolderFileEntity shareFolderFileEntity : shareFiles) {
            if (shareFolderFileEntity.getFileId() != null) {
                String id = shareFolderFileEntity.getFileId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    shareIdModel.getRootFileIds().add(id);
                } else {
                    shareIdModel.getFileIds().add(id);
                }
            } else {
                String id = shareFolderFileEntity.getFolderId();
                if (shareFolderFileEntity.getIsRoot() == 0) {
                    shareIdModel.getRootFolderIds().add(id);
                } else {
                    shareIdModel.getFolderIds().add(id);
                }
            }
        }
        return shareIdModel;
    }
}
